import es
import playerlib
import random

import wcs

raceName = "Pandaren Brewmaster"
race     = wcs.races[raceName]

""" Load the strings into the variable text """
text     = race.loadStrings()

""" ############################### """
""" ### Begin the configuration ### """
""" ############################### """

config   = race.config()

config.text("********************")
config.text("Breath of Fire")
config.text("  When a player damages another player, they have a chance to")
config.text("  cause initial damage, followed by burn damage.")
config.text("********************")
config.text("")
breathMaxLevel          = config.cvar("breathMaxLevel",      5, "The maximum level for the Breath of Fire Skill")
breathLevelInterval     = config.cvar("breathLevelInterval", 2, "The intervals between the abilities to upgrade their Breath of Fire skill")
breathDamage            = config.cvar("breathDamage",        3, "This is the amount of additional damage gave multiplied by their level")

config.text("")
config.text("********************")
config.text("Drunken Brawler")
config.text("    This skill gives a chance to dodge attacks, and deal more damage")
config.text("********************")
config.text("")
brawlerMaxLevel         = config.cvar("brawlerMaxLevel",      5, "The maximum level for the Drunken Brawler skill")
brawlerLevelInterval    = config.cvar("brawlerLevelInterval", 3, "The intervals between the abilities to upgrade their Drunken Brawler skill")
brawlerPercentage       = config.cvar("brawlerPercentage",   10, "The percent of the real damage that will be dealt to the victim, multiplied via their level.") 

config.text("")
config.text("********************")
config.text("Drunken Haze")
config.text("  Decrease victims speed")
config.text("********************")
config.text("")
hazeMaxLevel            = config.cvar("hazeMaxLevel",      5, "The maximum level for the Drunken Haze skill")
hazeLevelInterval       = config.cvar("hazeLevelInterval", 5, "The intervals between the abilities to upgrade their Reincarnation skill")
config.text("This is relative to the players level, and determines how long the player will be slowed for.")
hazePercent             = config.cvar("hazePercent",      50, "For example, if this was 50, and the players level was 5, the player would be slowed for 2.5 seconds (50% of 5)")

config.text("")
config.text("********************")
config.text("Storm, Earth and Fire")
config.text("  This ultimate allows you to charge yourself ") 
config.text("  to become either storm, earth or fire. Each ") 
config.text("  element has its own special abilities and")
config.text("  attributes. The better the level, the longer the time.")
config.text("  allowed to be inside this mode.")
config.text("********************")
config.text("")
stormMinLevel           = config.cvar("stormMinLevel",        8,  "The level required before this ultimate can be bought")
stormMaxLevel           = config.cvar("stormMaxLevel",        8,  "The maximum level for the Storm, Earth and Fire skill")
stormLevelInterval      = config.cvar("stormLevelInterval",   4,  "The interval between the skill upgrades")
stormCoolDown           = config.cvar("stormCoolDown",        45, "The amount of seconds after a player has used their ultimate that they cannot use it again")
stormTime               = config.cvar("stormTime",            4,  "The amount of time stayed in the element form, multiplied by their level.")

config.load(True)

""" ##################### """
""" ### END OF CONFIG ### """
""" ##################### """

race.registerSkill("Breath of Fire", int(breathMaxLevel), int(breathLevelInterval), "Cause initial damage, followed by burn damage.")
race.registerSkill("Drunken Haze", int(hazeMaxLevel), int(hazeLevelInterval), "Your victims speed decreases")
race.registerSkill("Drunken Brawler", int(brawlerMaxLevel), int(brawlerLevelInterval), "Have a chance to dodge enemy attacks, and deal more damage.")
race.registerUltimate("Storm, Earth and Fire", int(stormMinLevel), int(stormMaxLevel), int(stormLevelInterval), "Turn into Fire, Earth or Storm!")

race.registerMinLevel(30)
race.registerTeamLimit(3)

def load():
    """
    Executed when this race loads, ensure that the eventscripts_noisy is
    assigned to 1 so that the event player_footstep is executed.
    """
    es.doblock("corelib/noisy_on")
    
def unload():
    """
    Executed wehn this race unloads, ensure that we decrease the reference
    counter to the eventscripts_noisy variable, so that if no more scripts are
    using the event, then it can be disbaled.
    """
    es.doblock("corelib/noisy_off")
        
def player_death(event_var):
    """
    Executed when a player dies, ensure that we remove any effects that the
    player had active if they were under transformation of the ultimate
    """
    userid = event_var["userid"]
    player = wcs.players[userid]
    if player[raceName]["Storm, Earth and Fire"]:
        if player["brewCounter"]:
            transformBack(userid)
            
def player_hurt(event_var):
    """
    Executed when a player is damaged. Test to see if the victim has a level in
    drunken braweler, if so, then make a 5 x level% chance of dodging the atack.
    Test to see if the attacker has a drunken brawler, drunken haze or breath
    of fire levels; if so, handle the effects accordingly.
    """
    userid   = event_var["userid"]
    attacker = event_var["attacker"]
    wcsUserid = wcs.players[userid]
    wcsAttacker = wcs.players[attacker]
    if not int(es.getplayerprop(userid, "CBasePlayer.pl.deadflag")):
        dblevelu = wcsUserid[raceName]["Drunken Brawler"]
        dblevela = wcsAttacker[raceName]["Drunken Brawler"]
        dhlevel  = wcsAttacker[raceName]["Drunken Haze"]
        boflevel = wcsAttacker[raceName]["Breath of Fire"]
        damage = wcs.getDamage(event_var)
        if dblevelu and (random.randint(1, 20) <= dblevelu):
            wcsUserid.heal(damage)
            es.tell(userid, "#multi", text("drunken brawler dodge", lang = playerlib.getPlayer(userid).get("lang")))
            
        if dblevela and damage > 20 and (random.randint(1, 20) <= dblevela):
            wcsUserid.damage(int(damage * dblevela * (int(brawlerPercentage) / 100.)), 32, attacker)
            es.tell(attacker, "#multi", text("drunken brawler damage", lang = playerlib.getPlayer(attacker).get("lang")))
            
        if dhlevel and (random.randint(1,20) <= dhlevel):
            wcsUserid.speedAdd(dhlevel * -0.05)
            wcsUserid.delayed(dhlevel * (int(hazePercent) / 100.), normalSpeed, (userid, attacker, dhlevel))
            es.tell(attacker, "#multi", text("drunken haze", lang = playerlib.getPlayer(attacker).get("lang")))
            
        if boflevel and (random.randint(1,20) <= boflevel):
            wcsUserid.damage(boflevel * int(breathDamage), 32, attacker)
            wcsUserid.burn(boflevel)
            es.tell(attacker, "#multi", text("breath of fire", lang = playerlib.getPlayer(attacker).get("lang")))
            
def player_footstep(event_var):
    """
    Executed whenever a player takes a footstep. If the player is currently
    transformed, then ensure that all enemies within range of the person are
    effected by the player's element.
    """
    userid = event_var["userid"]
    player = wcs.players[userid]
    level = player[raceName]["Storm, Earth and Fire"]
    if level and player["brewElement"]:
    
        element = player["brewElement"]
        filt    = "#t" if es.getplayerteam(userid) == 3 else "#ct"

        if element == "Fire":
            #wcs.effect.Follow(userid, 255, 0, 0)
            #wcs.effect.Ring3(userid, random.randint(20,80), random.randint(1,3), 255, 0, 0)
            player.near(level * 50, burn, filt)
            
        elif element == "Storm":
            sound = "player/footsteps/mud%s.wav" % random.randint(1, 4)
            es.emitsound("player", userid, sound, 1.0, 0.4)
            #wcs.effect.Ring1(userid, 30, 1, 0, 0, 255)
            #player.delayed(1, wcs.effect.Ring1, (userid, 50, 1, 0, 0, 255))
            player.near(level * 50, shock, filt)
            
        elif element == "Earth":
            sound = "ambient/explosions/explode_%s.wav" % random.choice((5, 8, 9))
            es.emitsound("player", userid, sound, 1.0, 0.0)
            #wcs.effect.Ring2(userid, random.randint(80, 100), 1, 128, 128, 128) 
            player.near(level * 50, shake, filt)

def burn(userid, attacker):
    """
    Executed for every player within range of the attacker when he walks. This
    occurs when the attacker is transformed into 'Fire'. Burn the victims for
    5 seconds
    """
    wcs.players[userid].burn(5)

def shock(userid, attacker):
    """
    Shocks enemies in range of the attacker when he walks. This occurs when the
    attacker is transformed into 'Storm'. Freeze the plyer and shake their 
    screen to distort their view.
    """
    player = wcs.players[userid]
    player.freeze(1)
    player.shake(1, 3)
    es.emitsound("player", userid, "ambient/energy/zap3.wav", "0.5", "0.6")
    #wcs.effect.Beam1(attacker, userid, 3, random.randint(1,255), 0, random.randint(1,255))
    
def shake(userid, attacker):
    """
    Shakes a player in range of the attacker when they are in range of them
    whilst walking. This occurs when the attacker is in 'Earth'. This pushes
    victims 150 game units on the z axis, distorts their view, and has a 20%
    chance of forcing the client to drop their weapon.
    """
    player = wcs.players[userid]
    player.shake(2, 5)
    player.push(0, 0, 150)
    if random.randint(1, 5) == 1:
        player.drop()
    #wcs.effect.Ring2(userid, 100, 2, 255, 255, 255)
        
def normalSpeed(userid, attacker, dhlevel):
    """
    Executed when we want to reset a victim back to the player's normal speed.
    This occurs when the victim has been affected by the Drunken Haze effect.
    
    @param int userid The ID of the user who is affected by the drunken haze
    @param int attacker The ID of the user who casted the drunken haze
    @param int dhlevel The level of the drunken haze effect which effected the victim
    """
    if not es.getplayerprop(userid, "CBasePlayer.pl.deadflag"):
        wcs.players[userid].speedAdd(dhlevel * 0.05)
        
def player_ultimate_on(event_var):
    """
    Executed when the player has held down their ultimate key, begin the counter
    which will transform them into different entities.
    """
    userid = event_var["userid"]
    player = wcs.players[userid]
    storm = player[raceName]["Storm, Earth and Fire"]
    if storm:
        player["brewElement"] = None
        player["brewCounter"] = 0
        increment(userid)

def increment(userid):
    """
    Executed at each iteration per second. Charge up the player by 1 more
    count. If the loop is 10, then ensure that we force the player to let go
    of their ultimate key and transform.
    """
    player = wcs.players[userid]
    player.freeze(1)
    loopCounter = player["brewCounter"]
    es.emitsound("player", userid, wcs.BLIP, 0.5, 0.5)
    #wcs.effect.Ring2(userid, loopCounter * 15, 11 - loopCounter, random.randint(1,255), random.randint(1,255), random.randint(1,255))
    if loopCounter < 10:
        player.hudHint("%s\n%s" % (text("charging", lang = playerlib.getPlayer(userid).get("lang")), "|" * (loopCounter + 1)))
        player["brewCounter"] += 1
        player.delayedName(1, "brew", increment, userid)
    else:
        es.cexec(userid, "-ultimate")
        
def player_ultimate_off(event_var):
    """
    Executed when the player has prematurely let go of their ultimate key. Test
    to see if they have waited 10 seconds for the transofmration, if som then
    transform them into either Storm, Earth or Fire.
    """
    userid = event_var["userid"]
    player = wcs.players[userid]
    storm  = player[raceName]["Storm, Earth and Fire"]
    if storm:
        player.cancelDelayed("brew")
        if not int(event_var["cooldown"]):
            looped = player["brewCounter"]
            if looped < 10:
                player.setCoolDown("Storm, Earth and Fire", looped)
            else:
                element = random.choice(["Storm", "Earth", "Fire"])
                player.setCoolDown("Storm, Earth and Fire", int(stormCoolDown))
                player["brewElement"] = element
                
                if element == "Storm":
                    alpha = player["minAlpha"]
                    player.color(wcs.GREY, alpha=alpha/2.0)
                    player.changeGravity(-0.3)
                    player.speedAdd(0.3)
                    atmosphereStorm(userid)
                    
                elif element == "Earth":
                    player.color(wcs.BROWN)
                    player.changeGravity(0.3)
                    player.speedAdd(-0.3)
                    player.healthAdd(100)
                else:
                    player.color(wcs.RED)
                    es.emitsound("player", userid, "ambient/fire/mtov_flame2.wav", 1.0, 0.0)
                tokens            = {}
                tokens["element"] = element
                es.tell(userid, "#multi", text("transformed", tokens, playerlib.getPlayer(userid).get("lang")))
                player["brewCounter"] = storm * int(stormTime)
                player.delayedName(1, "decrement", decrement, userid)
            
def atmosphereStorm(userid):
    """
    Executed every 4 seconds to create an atmosphreic storm noise.
    
    @param int userid The ID of the person to emmit the atmosphere noise
    """
    es.emitsound("player", userid, "ambient/atmosphere/thunder%s.wav" % random.randint(1,4), 1.0, 0.0)
    wcs.players[userid].delayedName(4, "sfx", atmosphereStorm, userid)

def round_end(event_var):
    """
    Executed when the round is over, transform everyone back to normal who were
    transformed within the 
    """
    for player in es.getUseridList():
        wcsPlayer = wcs.players[player]
        if wcsPlayer[raceName]["Storm, Earth and Fire"]:
            if wcsPlayer["brewCounter"]:
                transformBack(player)
            
def decrement(userid):
    """
    Creates a timer which loops and decreases every second telling the player
    how long they have left as a transfomred beast.
    
    @param int userid The ID of the user who needs their timer ticker decreasing
    """
    player = wcs.players[userid]
    currentLoop = player["brewCounter"]
    if currentLoop:
        tokens = {}
        tokens["element"] = player["brewElement"]
        tokens["time"]    = currentLoop
        player.hudHint("%s\n%s" % (text("time left", tokens, playerlib.getPlayer(userid).get("lang")), text("seconds", tokens, playerlib.getPlayer(userid).get("lang"))))
        player["brewCounter"] -= 1
        player.delayedName(1, "decrement", decrement, userid)
    else:
        transformBack(userid)
        
def transformBack(userid):
    """
    Removes any effects that the transformation gives to the player.
    
    @param int userid The ID of the user to trasnform back.
    """
    player = wcs.players[userid]
    player.cancelDelayed("decrement")
    player.cancelDelayed("sfx")
    del player["brewElement"]
    del player["brewCounter"]
    player.color()
    player.health(100)
    player.setGravity(1.0)
    player.speed(1.0)
    es.tell(userid, "#multi", text("transformed back", lang = playerlib.getPlayer(userid).get("lang")))
